package com.mallcai.bigdata.ladon.service.peekdata;

import com.mallcai.bigdata.ladon.dpl.entity.peekdata.ModelMeta;
import com.mallcai.bigdata.ladon.dpl.entity.peekdata.PeekRule;
import com.mallcai.bigdata.ladon.dpl.vo.DataType;
import com.mallcai.bigdata.ladon.dpl.vo.DatasourceType;
import com.mallcai.bigdata.ladon.dpl.vo.PeekRuleType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import tk.mybatis.mapper.util.Assert;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created by oneape<oneape15@163.com>
 * Created 2019-06-09 20:58.
 * Modify:
 */
@Slf4j
public class RuleFactory {
    /**
     * 根据数据类型获取到相应的规则
     *
     * @param dt DataType
     * @return List
     */
    public static List<PeekRuleType> getRuleByDataType(DataType dt) {
        List<PeekRuleType> prts = new ArrayList<>();
        if (dt == DataType.STRING) {
            prts.add(PeekRuleType.EQUALS);
            prts.add(PeekRuleType.EQUALS_IGNORE_CASE);
            prts.add(PeekRuleType.NOT_EQUALS);
            prts.add(PeekRuleType.END_WITH);
            prts.add(PeekRuleType.START_WITH);
            prts.add(PeekRuleType.INCLUDES);
            prts.add(PeekRuleType.NOT_INCLUDES);
            prts.add(PeekRuleType.CONTAINS);
        } else if (dt == DataType.INTEGER ||
                dt == DataType.LONG ||
                dt == DataType.FLOAT ||
                dt == DataType.DOUBLE) {
            prts.add(PeekRuleType.EQUALS);
            prts.add(PeekRuleType.NOT_EQUALS);
            prts.add(PeekRuleType.GT);
            prts.add(PeekRuleType.GTE);
            prts.add(PeekRuleType.LT);
            prts.add(PeekRuleType.LTE);
            prts.add(PeekRuleType.INCLUDES);
            prts.add(PeekRuleType.NOT_INCLUDES);
        } else if (dt == DataType.DATE ||
                dt == DataType.TIME ||
                dt == DataType.DATETIME ||
                dt == DataType.TIMESTAMP) {
            prts.add(PeekRuleType.EQUALS);
            prts.add(PeekRuleType.GT);
            prts.add(PeekRuleType.GTE);
            prts.add(PeekRuleType.LT);
            prts.add(PeekRuleType.LTE);
        } else {
            prts.add(PeekRuleType.EQUALS);
        }

        return prts;
    }

    /**
     * 根据规则与字段类型生成查询条件
     *
     * @param dst   DatasourceType
     * @param rules List
     * @param mms   List
     * @return String
     */
    public static String formatRuleString(DatasourceType dst, List<PeekRule> rules, List<ModelMeta> mms) {
        if (dst == null) {
            return null;
        }
        Assert.isTrue(mms != null, "字段类型为空");
        Assert.isTrue(rules != null, "规则为空");
        Map<String, DataType> map = new HashMap<>();
        mms.forEach(m -> map.put(m.getName(), DataType.getByCode(m.getDataType())));

        StringBuilder sb = new StringBuilder();
        int index = 0;
        for (PeekRule r : rules) {
            PeekRuleType prt = PeekRuleType.getByCode(r.getRule());
            if (prt == null) {
                continue;
            }
            DataType dt = map.get(r.getFieldName());
            if (dt == null) {
                continue;
            }

            // 规则异常,直接跳过
            String ruleString = ruleString(dst, dt, prt, r.getValue());
            if (StringUtils.isBlank(ruleString)) {
                continue;
            }

            if (index > 0) {
                sb.append(" AND ");
            }
            sb.append(r.getFieldName()).append(" ").append(ruleString);
            index++;
        }
        return sb.toString();
    }

    private static String ruleString(DatasourceType dst, DataType dt, PeekRuleType prt, String value) {
        String tmp = StringUtils.trimToEmpty(value);
        if (dt == DataType.STRING) {
            if (!PeekRuleType.isStringRule(prt)) {
                log.warn("规则不属于字符串类型, value: {}", tmp);
                return null;
            }
            if (prt == PeekRuleType.EQUALS || prt == PeekRuleType.EQUALS_IGNORE_CASE) {
                return " = '" + tmp + "' ";
            }
            if (prt == PeekRuleType.NOT_EQUALS) {
                return " != '" + tmp + "' ";
            }
            if (prt == PeekRuleType.START_WITH) {
                return " LIKE '" + tmp + "%' ";
            }
            if (prt == PeekRuleType.END_WITH) {
                return " LIKE '%" + tmp + "' ";
            }
            if (prt == PeekRuleType.CONTAINS) {
                return " LIKE '%" + tmp + "%' ";
            }
            if (prt == PeekRuleType.INCLUDES) {
                return " IN " + toInStr(tmp , true);
            }
            if (prt == PeekRuleType.NOT_INCLUDES) {
                return " NOT IN " + toInStr(tmp, true);

            }
        } else {
            if (!PeekRuleType.isNumRule(prt)) {
                log.warn("规则不属于数字类型, value: {}", tmp);
                return null;
            }
            if (dt == DataType.TIMESTAMP || dt == DataType.TIME
                    || dt == DataType.DATE || dt == DataType.DATETIME ){
                if (!tmp.startsWith("'")){
                    tmp = "'"+tmp+"'";
                }
            }
            if (prt == PeekRuleType.EQUALS) {
                return " = " + tmp;
            }
            if (prt == PeekRuleType.NOT_EQUALS) {
                return " != " + tmp;
            }
            if (prt == PeekRuleType.GT) {
                return " > " + tmp;
            }
            if (prt == PeekRuleType.GTE) {
                return " >= " + tmp;
            }
            if (prt == PeekRuleType.LT) {
                return " < " + tmp;
            }
            if (prt == PeekRuleType.LTE) {
                return " <= " + tmp;
            }
            if (prt == PeekRuleType.INCLUDES) {
                return " IN " + toInStr(tmp, false);
            }
            if (prt == PeekRuleType.NOT_INCLUDES) {
                return " NOT IN " + toInStr(tmp, false);
            }
        }

        return null;
    }


    public static String ruleString(DataType dt, PeekRuleType prt, String value) {
        return ruleString(null, dt, prt, value);
    }


    private static String toInStr(String str, boolean needQuota){
        if (str != null){
            String preSuffix = needQuota ? "'" : "";
            String[] split = str.split(",");
            return Arrays.stream(split).map(String::trim).filter(StringUtils::isNotEmpty)
                    .map(item -> String.format("%s%s%s", preSuffix, item, preSuffix))
                    .collect(Collectors.joining(",", "(", ")"));
        }
        return null;

    }

    public static void main(String[] args) {

        System.out.println(toInStr("1, 2232,  34343, adsd,dsafd", true));
        System.out.println(toInStr("1, 2232,  34343, adsd,dsafd", false));
    }
}
